package com.jm88.tools.myapp;

import java.io.File;
import java.io.Writer;
import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.output.FileWriterWithEncoding;
import org.apache.commons.lang.StringUtils;

import com.jm88.tools.bean.TypeNode;

import freemarker.template.Configuration;
import freemarker.template.DefaultObjectWrapper;
import freemarker.template.Template;

/**
 * 用于宝钢电子交易平台-后台代码-自动创建:
 * Dao, Service, Action, Form, hibrenate Mapping Xml file, Struts xml file, spring bean xml file.
 *
 * @author guanweichen
 * @version 2010-11-20
 */
public class BsteelCreateCode {

	public static void main(String[] args) throws Exception{
		
		List<Class<?>> listBeanClass = new ArrayList<Class<?>>();
		List<String> listDescriptions = new ArrayList<String>();
		List<String> listSequences = new ArrayList<String>();
    	//listBeanClass.add();
		//listDescriptions.add();
		//listSequences.add();
		listBeanClass.add(TypeNode.class);
		listDescriptions.add("属性设置");
		listSequences.add("SEQ_TYPE_NODE");
    	// 清空target目录 的ibatis 目录
        FileUtils.cleanDirectory(new File("target/bsteel"));
    	
        for (int i = 0; i < listBeanClass.size(); i++) {
			
        	writerFiles(listBeanClass.get(i), listSequences.get(i), listDescriptions.get(i));
		}
	}
	
	/**
	 * @param clazz
	 * @param sequence 数据库sequence
	 * @param description 注释
	 * @throws Exception
	 */
	private static void writerFiles(Class<?> clazz, String sequence, String description) throws Exception {
    	
        Class<?> beanClass = clazz;
        Map<Object, Object> root = new HashMap<Object, Object>();
        List<Map<Object, Object>> props = getPropertys(beanClass);
        /*
         * 往root 里面存放数据,在模板中使用${"tableName"}
         */
        root.put("properties", props);
        root.put("tableName", getColumnName(beanClass.getSimpleName()));
        root.put("className", beanClass.getName());
        root.put("beanName", beanClass.getSimpleName());
        root.put("uncapitalizeBeanName", StringUtils.uncapitalize(beanClass.getSimpleName()));
        /*
         * 设置package 路径.
         */
        // TODO 使用时修改
        root.put("package", "com.bsteel.test");
        root.put("beanPackage", "com.bsteel.test");
        root.put("jspPath", "/jsp/basesetting/other/submarket");
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        root.put("createDate", dateFormat.format(new Date()));
        root.put("author", "guanweichen");
        root.put("description", description);
        root.put("sequence", sequence);
        
        Configuration cfg = new Configuration();
        // 设置一个数据源,当调用Class.getResource()来加载此数据模板.
        cfg.setClassForTemplateLoading(SSIApp.class, "/");
        // 设置对象包装用于包装对象模板模型
        cfg.setObjectWrapper(new DefaultObjectWrapper());
        cfg.setDefaultEncoding("utf-8");
        // 创建目录
        new File("target/bsteel").mkdir();
        new File("target/bsteel/dao").mkdir();
        new File("target/bsteel/dao/impl").mkdir();
        new File("target/bsteel/service").mkdir();
        new File("target/bsteel/service/impl").mkdir();
        new File("target/bsteel/action").mkdir();
//        new File("target/bsteel/form").mkdir();
        new File("target/bsteel/conf").mkdir();
        new File("target/bsteel/jsp").mkdir();
        // 各个文件生成路径
        String daoUrl = "target/bsteel/dao";
        String daoImplUrl = "target/bsteel/dao/impl";
        String serviceUrl = "target/bsteel/service";
        String serviceImplUrl = "target/bsteel/service/impl";
        String actionUrl = "target/bsteel/action";
//        String actionFormUrl = "target/bsteel/form";
        String configUrl = "target/bsteel/conf";
        String jspUrl = "target/bsteel/jsp";
        
        //个文件名
        String daoFileName = beanClass.getSimpleName() + "Dao.java";
        String daoImplFileName = beanClass.getSimpleName() + "DaoImpl.java";
        String serviceFileName = beanClass.getSimpleName() + "Service.java";
        String serviceImplFileName = beanClass.getSimpleName() + "ServiceImpl.java";
        String actionFileName = beanClass.getSimpleName() + "Action.java";
//        String actionFormName = beanClass.getSimpleName() + "Form.java";
        String configName = beanClass.getSimpleName() + "Config.xml";
        String hibernateMappingName = beanClass.getSimpleName() + ".hbm.xml";
        
        String jspListName = StringUtils.uncapitalize(beanClass.getSimpleName()) + "List.jsp";
        String jspSaveName = StringUtils.uncapitalize(beanClass.getSimpleName()) + "Save.jsp";
        String jspEditName = StringUtils.uncapitalize(beanClass.getSimpleName()) + "Edit.jsp";
        
        /*
         * 获得所有模板.
         */
        // TODO 切换数据库时切换sql-map 模板.
        Template tempDao = cfg.getTemplate("bsteel/dao.ftl");
        Template tempDaoImpl = cfg.getTemplate("bsteel/daoImpl.ftl");
        Template tempService = cfg.getTemplate("bsteel/service.ftl");
        Template tempServiceImpl = cfg.getTemplate("bsteel/serviceImpl.ftl");
        Template tempAction = cfg.getTemplate("bsteel/action.ftl");
//        Template tempActionForm = cfg.getTemplate("bsteel/actionForm.ftl");
        Template tempConfig = cfg.getTemplate("bsteel/config.ftl");
        Template tempHibernateMapping = cfg.getTemplate("bsteel/hibernate.ftl");
        Template nullConfig = cfg.getTemplate("bsteel/null.ftl");
        /*
         * 写出文件. 
         */
        writerFile(tempDao, root, daoUrl, daoFileName);
        writerFile(tempDaoImpl, root, daoImplUrl, daoImplFileName);
        writerFile(tempService, root, serviceUrl, serviceFileName);
        writerFile(tempServiceImpl, root, serviceImplUrl, serviceImplFileName);
        writerFile(tempAction, root, actionUrl, actionFileName);
//        writerFile(tempActionForm, root, actionFormUrl, actionFormName);
        writerFile(tempConfig, root, configUrl, configName);
        writerFile(nullConfig, root, jspUrl, jspEditName);
        writerFile(nullConfig, root, jspUrl, jspListName);
        writerFile(nullConfig, root, jspUrl, jspSaveName);
        writerFile(tempHibernateMapping, root, configUrl, hibernateMappingName);
    }

    private static void writerFile(Template template, Map<Object, Object> data, String fileUrl, String fileName) throws Exception{
    	Writer out = new FileWriterWithEncoding(new File(fileUrl, fileName), "utf-8");
        // 将模板数据以Map 方式,进行传输,经过内部处理,转化成模板(ibatis.ftl)中用到的freemarker标签处,传入到写出流里面.
    	template.process(data, out);
        out.close();
        System.out.println(fileName + "'s file writed success");
    }
    
    /**
     * 自省bean 的属性,已经列名,类型明.
     *
     * @param clazz
     * @return
     */
    private static List<Map<Object, Object>> getPropertys(Class<?> clazz){
    	List<Map<Object, Object>> props = new ArrayList<Map<Object, Object>>();
    	
    	for (Field field : clazz.getDeclaredFields()) {
            Map<Object, Object> m = new HashMap<Object, Object>();
            if (!"class".equals(field.getName()) && !"serialVersionUID".equals(field.getName())) {
                m.put("propertyName", field.getName());
                m.put("propertyTypeName", field.getType().getName());
                m.put("columnName", getColumnName(field.getName()));
                props.add(m);
            }
        }
    	return props;
    }
    
    /**
     * 得到字段对应在数据库中的名字.例如: GbArea --> GB_AREA
     *
     * @param propName
     * @return
     */
    private static String getColumnName(String propName) {
        char[] chars = propName.toCharArray();
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < chars.length; i++) {
            char c = chars[i];
            if (Character.isUpperCase(c) && i > 0) {
                sb.append('_').append(c);
            } else {
                sb.append(c);
            }
        }
        return sb.toString().toUpperCase();
    }

}
